#ifndef ALGO_ALGOBASE
#define ALGO_ALGOBASE
#include <utility/spw_move_in.h>
#include <iterator/spw_iterator.h>
namespace spwstd{
namespace spwalg{

template<typename InputIter>
using RequireInputIter
    = typename std::enable_if_t<
        std::is_convertible<
            typename spwstd::IteratorTraits<InputIter>::IteratorCategory, 
            spwstd::InputIterTag>::value>;

template<typename BIter>
using RequireBidirectIter
    = typename std::enable_if_t<
        std::is_convertible<
            typename spwstd::IteratorTraits<BIter>::IteratorCategory, 
            spwstd::BidirectionalIterTag>::value>;

template<typename BIt1, typename BIt2, typename = RequireBidirectIter<BIt1>, 
   typename= RequireBidirectIter<BIt2> >
BIt2 copyBackward(BIt1 first, BIt1 last, BIt2 d_last)
{
    // 要保证bidirectionaliterator
    while (first != last)
        *(--d_last) = *(--last);
    return d_last;
}
// copy
template<typename InputIterator, typename OutputIterator>
inline OutputIterator
copy(InputIterator first, InputIterator last, OutputIterator dest) 
{
    for(; first != last; ++first, ++dest) {
        *dest = *first;
    }
    return dest;
}

//fill
template<typename ForwardIter, typename Tp>
inline void
fill(ForwardIter first, ForwardIter last, const Tp& value) 
{
    for(; first != last; ++first)
        *first = value;
}

// 从迭代器first开始填充n个类型为valueT的value
template<typename OutputIterator, typename SizeT, typename ValueT>
inline OutputIterator
fillN(OutputIterator first, SizeT n , const ValueT& value) {
    for(SizeT i=0; i < n; ++i) {
        *first++ = value;
    }
    return first;
}

 template<typename ForwardIterator1, typename ForwardIterator2>
 inline void iterSwap(ForwardIterator1& a, ForwardIterator2& b) {
     spwstd::spwuti::swap(*a, *b);
 }


template<typename ForwardIterator1, typename ForwardIterator2>
ForwardIterator2 swapRanges(ForwardIterator1 first1, ForwardIterator1 end1,
        ForwardIterator2 first2) 
{
    // 检测ForwardIterator1,2是否指向可以改变的值
    // 检测first1-end1的范围是否合理

    for(;first1 != end1; ++first1, ++first2) {
        iterSwap(first1, first2);
    }

    return first2;
}

} // namespace spwalg
} // namespace spwstd
#endif // ALGO_ALGOBASE
